package com.example.demo2.common.check;

import java.util.LinkedHashMap;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

/**
 */
public final class CheckError implements java.io.Serializable {
	private static final long serialVersionUID = 1L;
	private static Log log = LogFactory.get();

	private int code;
	private String msg;
	private String debugMessage;
	private Throwable cause;

	public CheckError(Builder builder) {
		this.code = builder.code;
		this.msg = builder.msg;
		this.debugMessage = builder.debugMessage;
		this.cause = builder.cause;
	}

	public int getCode() {
		return code;
	}

	public String getMsg() {
		return msg;
	}

	public String getDebugMessage() {
		return debugMessage;
	}

	public Throwable getCause() {
		return cause;
	}

	public static Builder builder() {
		return new Builder();
	}

	public String getExceptionMessage() {
		return String.format("%s: %s", code, msg);
	}

	@Override
	public String toString() {
		LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
		map.put("code", code);
		map.put("msg", msg);
		map.put("debugMessage", debugMessage);
		return String.format("%s-%s", this.getClass().getSimpleName(), map);
	}

	public static class Builder {
		private Throwable cause;
		private int code;
		private String debugMessage;
		private String msg;

		private Builder() {
		}

		public CheckError build() {
			this.msg = msg == null ? "服务器开小差了:)" : msg;
			return new CheckError(this);
		}

		public Builder code(int code) {
			this.code = code;
			return this;
		}

		/**
		 * Check#code为i18n objectErrors，可以用此方法设置message中的参数.
		 */
		public Builder msg(String msg) {
			this.msg = msg;
			return this;
		}

		/**
		 * Fail#debugMessage.
		 */
		public Builder debugMessage(String msg, Object... args) {
			this.debugMessage = String.format(msg, args);
			return this;
		}

		public Builder cause(Throwable e) {
			log.error(e, "Check校验类抛出异常");
			this.cause = e;
			return this;
		}

		public Builder visit(Check.ErrorBuilderVisitor visitor) {
			visitor.call(this);
			return this;
		}
	}

}
